home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / RTrace-1.0-src / shadmod1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-24  |  16.9 KB  |  448 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
  3.  * All rights reserved.
  4.  *
  5.  * This code received contributions from the following people:
  6.  *
  7.  *  Roman Kuchkuda      - basic ray tracer
  8.  *  Mark VandeWettering - MTV ray tracer
  9.  *  Augusto Sousa       - overall, shading model
  10.  *  Craig Kolb          - textures
  11.  *  David Buck          - textures
  12.  *
  13.  * Redistribution and use in source and binary forms are permitted
  14.  * provided that the above copyright notice and this paragraph are
  15.  * duplicated in all such forms and that any documentation,
  16.  * advertising materials, and other materials related to such
  17.  * distribution and use acknowledge that the software was developed
  18.  * by Antonio Costa, at INESC-Norte. The name of the author and
  19.  * INESC-Norte may not be used to endorse or promote products derived
  20.  * from this software without specific prior written permission.
  21.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  22.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  23.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  24.  */
  25. #include "defs.h"
  26. #include "extern.h"
  27.  
  28. /**********************************************************************
  29.  *    RAY TRACING - Shade Model 1 - Version 7.0                       *
  30.  *                                                                    *
  31.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  32.  *    ADAPTED BY : Antonio Costa, INESC-Norte, June 1989              *
  33.  *    MODIFIED BY: Antonio Costa, INESC-Norte, March 1992             *
  34.  **********************************************************************/
  35.  
  36. /***** Shading Phong model *****/
  37. #define LEFT  (1 SHL shade_level)
  38. #define RIGHT (1 SHL (shade_level + 1))
  39.  
  40. #ifdef THINK_C
  41.  
  42. /* On the mac, SCREEN_SIZE_X_MAX is not a constant, so previous_repetitions
  43.     is set manually from the mac segment */
  44.         
  45. short int previous_repetitions;
  46.  
  47. #else
  48.  
  49. static short int  previous_repetitions = SCREEN_SIZE_X_MAX;
  50.  
  51. #endif
  52.  
  53. static xyz_struct previous_normal, previous_reflected;
  54. static rgb_struct previous_diffuse, previous_specular;
  55. void
  56. shade_phong(position, normal, ray, object, color)
  57.   xyz_ptr         position, normal;     /* Normal may be modified */
  58.   ray_ptr         ray;
  59.   object_ptr      object;
  60.   rgb_ptr         color;
  61. {
  62.   REG int         l;
  63.   REG real        k, diffuse, specular;
  64.   real            intensity, new_diffuse;
  65.   boolean         refractive, opposite_light;
  66.   rgb_struct      brightness, level;
  67.   rgb_struct      surface_diffuse, surface_specular, surface_transparent;
  68.   rgb_struct      new_color, distributed_color;
  69.   xyz_struct      old_normal, old_reflected, lighting;
  70.   ray_struct      reflected, refracted, distributed;
  71.   surface_struct  new_surface;
  72.   int             id, ambient_diffuse_rays, ambient_specular_rays;
  73.  
  74.   STRUCT_ASSIGN(new_surface, *(surface[object->surface_id]));
  75.   k = -2.0 * DOT_PRODUCT(ray->vector, *normal);
  76.   reflected.vector.x = k * normal->x + ray->vector.x;
  77.   reflected.vector.y = k * normal->y + ray->vector.y;
  78.   reflected.vector.z = k * normal->z + ray->vector.z;
  79.   if (normal_mode == 0)
  80.   {
  81.     if (k < 0.0)
  82.     {
  83.       normal->x = -(normal->x);
  84.       normal->y = -(normal->y);
  85.       normal->z = -(normal->z);
  86.     }
  87.   } else
  88.   if ((k < 0.0) AND ray->inside)
  89.   {
  90.     normal->x = -(normal->x);
  91.     normal->y = -(normal->y);
  92.     normal->z = -(normal->z);
  93.   }
  94.   STRUCT_ASSIGN(old_normal, *normal);
  95.   if ((texture_mode != 0) AND(object->texture != NULL))
  96.   {
  97.     if (normal_check_mode AND object->texture_modify_normal)
  98.       STRUCT_ASSIGN(old_reflected, reflected.vector);
  99.     surface_texture(position, normal, &new_surface, object->texture);
  100.     if (normal_check_mode AND object->texture_modify_normal)
  101.     {
  102.       k = -2.0 * DOT_PRODUCT(ray->vector, *normal);
  103.       reflected.vector.x = k * normal->x + ray->vector.x;
  104.       reflected.vector.y = k * normal->y + ray->vector.y;
  105.       reflected.vector.z = k * normal->z + ray->vector.z;
  106.       if (DOT_PRODUCT(reflected.vector, old_normal) < ROUNDOFF)
  107.       {
  108.         STRUCT_ASSIGN(*normal, old_normal);
  109.         STRUCT_ASSIGN(reflected.vector, old_reflected);
  110.       }
  111.     }
  112.   }
  113.   STRUCT_ASSIGN(surface_diffuse, new_surface.diffuse);
  114.   STRUCT_ASSIGN(surface_specular, new_surface.specular);
  115.   STRUCT_ASSIGN(surface_transparent, new_surface.transparent);
  116.   new_surface.diffuse.r *= new_surface.color.r;
  117.   new_surface.diffuse.g *= new_surface.color.g;
  118.   new_surface.diffuse.b *= new_surface.color.b;
  119.   new_surface.specular.r *= new_surface.color.r * (1.0 -
  120.     new_surface.metal_factor.r) + new_surface.metal_factor.r;
  121.   new_surface.specular.g *= new_surface.color.g * (1.0 -
  122.     new_surface.metal_factor.g) + new_surface.metal_factor.g;
  123.   new_surface.specular.b *= new_surface.color.b * (1.0 -
  124.     new_surface.metal_factor.b) + new_surface.metal_factor.b;
  125.   new_surface.transparent.r *= new_surface.color.r;
  126.   new_surface.transparent.g *= new_surface.color.g;
  127.   new_surface.transparent.b *= new_surface.color.b;
  128.   color->r = 0.0;
  129.   color->g = 0.0;
  130.   color->b = 0.0;
  131.   /* Refractions */
  132.   refractive = FALSE;
  133.   if (COLOR_BIG(surface_transparent, ROUNDOFF)
  134.       AND(shade_level < last_shade_level))
  135.   {
  136.     level.r = ray->level.r * surface_transparent.r;
  137.     level.g = ray->level.g * surface_transparent.g;
  138.     level.b = ray->level.b * surface_transparent.b;
  139.     if (COLOR_BIG(level, threshold_level))
  140.     {
  141.       STRUCT_ASSIGN(refracted.vector, ray->vector);
  142.       if (refract(&refracted, normal, ray->inside, object->refraction))
  143.       {
  144.         refractive = TRUE;
  145.         if (shade_level < RAY_CACHE_LEVEL_MAX)
  146.           ray_node += RIGHT;
  147.         POSINC(shade_level);
  148.         if (shade_level > shade_level_max)
  149.           shade_level_max = shade_level;
  150.         STRUCT_ASSIGN(refracted.level, level);
  151.         refracted.inside = NOT ray->inside;
  152.         REALINC(refracted_rays);
  153.         if (SELF_INTERSECT(object->object_type, refracted.inside))
  154.           id = NO_OBJECTS;
  155.         else
  156.           id = object->id;
  157.         if (intersect_all(id, position, &refracted, &new_color) > 0.0)
  158.         {
  159.           color->r += new_color.r * new_surface.transparent.r;
  160.           color->g += new_color.g * new_surface.transparent.g;
  161.           color->b += new_color.b * new_surface.transparent.b;
  162.         } else
  163.         {
  164.           color->r += back_color.r * new_surface.transparent.r;
  165.           color->g += back_color.g * new_surface.transparent.g;
  166.           color->b += back_color.b * new_surface.transparent.b;
  167.         }
  168.         POSDEC(shade_level);
  169.         if (shade_level < RAY_CACHE_LEVEL_MAX)
  170.           ray_node -= RIGHT;
  171.       } else
  172.       {
  173.         /* TIR */
  174.         surface_specular.r += surface_transparent.r;
  175.         surface_specular.g += surface_transparent.g;
  176.         surface_specular.b += surface_transparent.b;
  177.         new_surface.specular.r = surface_specular.r * (new_surface.color.r *
  178.           (1.0 - new_surface.metal_factor.r) + new_surface.metal_factor.r);
  179.         new_surface.specular.g = surface_specular.g * (new_surface.color.g *
  180.           (1.0 - new_surface.metal_factor.g) + new_surface.metal_factor.g);
  181.         new_surface.specular.b = surface_specular.b * (new_surface.color.b *
  182.           (1.0 - new_surface.metal_factor.b) + new_surface.metal_factor.b);
  183.       }
  184.     }
  185.   }
  186.   /* Reflections */
  187.   if (COLOR_BIG(surface_specular, ROUNDOFF)
  188.       AND(shade_level < last_shade_level))
  189.   {
  190.     level.r = ray->level.r * surface_specular.r;
  191.     level.g = ray->level.g * surface_specular.g;
  192.     level.b = ray->level.b * surface_specular.b;
  193.     if (COLOR_BIG(level, threshold_level))
  194.     {
  195.       if (shade_level < RAY_CACHE_LEVEL_MAX)
  196.         ray_node += LEFT;
  197.       POSINC(shade_level);
  198.       if (shade_level > shade_level_max)
  199.         shade_level_max = shade_level;
  200.       STRUCT_ASSIGN(reflected.level, level);
  201.       reflected.inside = ray->inside;
  202.       REALINC(reflected_rays);
  203.       if (SELF_INTERSECT(object->object_type, reflected.inside))
  204.         id = NO_OBJECTS;
  205.       else
  206.         id = object->id;
  207.       if (intersect_all(id, position, &reflected, &new_color) > 0.0)
  208.       {
  209.         color->r += new_color.r * new_surface.specular.r;
  210.         color->g += new_color.g * new_surface.specular.g;
  211.         color->b += new_color.b * new_surface.specular.b;
  212.       } else
  213.       {
  214.         color->r += back_color.r * new_surface.specular.r;
  215.         color->g += back_color.g * new_surface.specular.g;
  216.         color->b += back_color.b * new_surface.specular.b;
  217.       }
  218.       POSDEC(shade_level);
  219.       if (shade_level < RAY_CACHE_LEVEL_MAX)
  220.         ray_node -= LEFT;
  221.     }
  222.   }
  223.   /* Ambient */
  224.   if ((shade_level >= last_ambient_level) OR(ambient_sample_rays == 0))
  225.   {
  226.     color->r += light_ambient.r * new_surface.diffuse.r;
  227.     color->g += light_ambient.g * new_surface.diffuse.g;
  228.     color->b += light_ambient.b * new_surface.diffuse.b;
  229.   } else
  230.   {
  231.     diffuse = (surface_diffuse.r + surface_diffuse.g +
  232.       surface_diffuse.b) / 3.0;
  233.     specular = (surface_specular.r + surface_specular.g +
  234.       surface_specular.b) / 3.0;
  235.     if (diffuse + specular > ROUNDOFF)
  236.     {
  237.       if (ABS(diffuse + specular - 1.0) > ROUNDOFF)
  238.       {
  239.         k = diffuse + specular;
  240.         diffuse /= k;
  241.         specular /= k;
  242.       }
  243.       if ((shade_level == 0) AND(distributed_cache_mode != 0)
  244.           AND(previous_repetitions <= distributed_cache_repetitions)
  245.           AND(DOT_PRODUCT(old_normal, previous_normal) > threshold_vector)
  246.           AND(DOT_PRODUCT(reflected.vector, previous_reflected) >
  247.               threshold_vector))
  248.       {
  249.         POSINC(previous_repetitions);
  250.         REALINC(distributed_cache_hits);
  251.         color->r += previous_diffuse.r * diffuse * new_surface.diffuse.r;
  252.         color->g += previous_diffuse.g * diffuse * new_surface.diffuse.g;
  253.         color->b += previous_diffuse.b * diffuse * new_surface.diffuse.b;
  254.         color->r += previous_specular.r * specular * new_surface.specular.r;
  255.         color->g += previous_specular.g * specular * new_surface.specular.g;
  256.         color->b += previous_specular.b * specular * new_surface.specular.b;
  257.       } else
  258.       {
  259.         ambient_diffuse_rays = estimate_diffuse(ambient_sample_rays, diffuse);
  260.         ambient_specular_rays = estimate_specular(ambient_sample_rays,
  261.           specular, new_surface.phong_factor);
  262.         if (shade_level < RAY_CACHE_LEVEL_MAX)
  263.           ray_node += RIGHT;
  264.         POSINC(shade_level);
  265.         if (shade_level > shade_level_max)
  266.           shade_level_max = shade_level;
  267.         if (SELF_INTERSECT(object->object_type, distributed.inside))
  268.           id = NO_OBJECTS;
  269.         else
  270.           id = object->id;
  271.         distributed.inside = ray->inside;
  272.         distributed.level.r = ray->level.r * surface_diffuse.r;
  273.         distributed.level.g = ray->level.g * surface_diffuse.g;
  274.         distributed.level.b = ray->level.b * surface_diffuse.b;
  275.         distributed_color.r = 0.0;
  276.         distributed_color.g = 0.0;
  277.         distributed_color.b = 0.0;
  278.         if (COLOR_BIG(surface_diffuse, ROUNDOFF)
  279.             AND COLOR_BIG(distributed.level, ROUNDOFF)
  280.             AND(ambient_diffuse_rays > 0))
  281.         {
  282.           /* Diffuse ambient */
  283.           for (l = 0; l < ambient_diffuse_rays; POSINC(l))
  284.           {
  285.             make_diffuse_vector(&old_normal, &(distributed.vector));
  286.             REALINC(ambient_rays);
  287.             if (intersect_all(id, position, &distributed, &new_color) > 0.0)
  288.             {
  289.               distributed_color.r += new_color.r;
  290.               distributed_color.g += new_color.g;
  291.               distributed_color.b += new_color.b;
  292.             } else
  293.             {
  294.               distributed_color.r += back_color.r;
  295.               distributed_color.g += back_color.g;
  296.               distributed_color.b += back_color.b;
  297.             }
  298.           }
  299.           k = 1.0 / (real) ambient_diffuse_rays;
  300.           distributed_color.r *= k;
  301.           distributed_color.g *= k;
  302.           distributed_color.b *= k;
  303.           color->r += distributed_color.r * diffuse * new_surface.diffuse.r;
  304.           color->g += distributed_color.g * diffuse * new_surface.diffuse.g;
  305.           color->b += distributed_color.b * diffuse * new_surface.diffuse.b;
  306.         }
  307.         if ((shade_level == 1) AND(distributed_cache_mode != 0))
  308.           STRUCT_ASSIGN(previous_diffuse, distributed_color);
  309.         distributed.level.r = ray->level.r * surface_specular.r;
  310.         distributed.level.g = ray->level.g * surface_specular.g;
  311.         distributed.level.b = ray->level.b * surface_specular.b;
  312.         distributed_color.r = 0.0;
  313.         distributed_color.g = 0.0;
  314.         distributed_color.b = 0.0;
  315.         if (COLOR_BIG(surface_specular, ROUNDOFF)
  316.             AND COLOR_BIG(distributed.level, ROUNDOFF)
  317.             AND(ambient_specular_rays > 0)
  318.             AND(new_surface.phong_factor > ROUNDOFF))
  319.         {
  320.           /* Specular ambient */
  321.           for (l = 0; l < ambient_specular_rays; POSINC(l))
  322.           {
  323.             make_specular_vector(&(reflected.vector), &old_normal,
  324.                                  new_surface.phong_factor,
  325.                                  &(distributed.vector));
  326.             REALINC(ambient_rays);
  327.             if (intersect_all(id, position, &distributed, &new_color) > 0.0)
  328.             {
  329.               distributed_color.r += new_color.r;
  330.               distributed_color.g += new_color.g;
  331.               distributed_color.b += new_color.b;
  332.             } else
  333.             {
  334.               distributed_color.r += back_color.r;
  335.               distributed_color.g += back_color.g;
  336.               distributed_color.b += back_color.b;
  337.             }
  338.           }
  339.           k = 1.0 / (real) ambient_specular_rays;
  340.           distributed_color.r *= k;
  341.           distributed_color.g *= k;
  342.           distributed_color.b *= k;
  343.           color->r += distributed_color.r * specular * new_surface.specular.r;
  344.           color->g += distributed_color.g * specular * new_surface.specular.g;
  345.           color->b += distributed_color.b * specular * new_surface.specular.b;
  346.         }
  347.         POSDEC(shade_level);
  348.         if (shade_level < RAY_CACHE_LEVEL_MAX)
  349.           ray_node -= RIGHT;
  350.         if ((shade_level == 0) AND(distributed_cache_mode != 0))
  351.         {
  352.           if (previous_repetitions > 0)
  353.           {
  354.             REALINC(distributed_cache_resets);
  355.             previous_repetitions = 0;
  356.           }
  357.           STRUCT_ASSIGN(previous_normal, old_normal);
  358.           STRUCT_ASSIGN(previous_reflected, reflected.vector);
  359.           STRUCT_ASSIGN(previous_specular, distributed_color);
  360.         }
  361.       }
  362.     }
  363.   }
  364.   new_surface.diffuse.r *= new_surface.diffuse_factor.r;
  365.   new_surface.diffuse.g *= new_surface.diffuse_factor.g;
  366.   new_surface.diffuse.b *= new_surface.diffuse_factor.b;
  367.   /* Lights */
  368.   for (l = 0; l < lights; POSINC(l))
  369.   {
  370.     vector_to_light(l, position, &lighting);
  371.     intensity = -1.0;
  372.     if ((texture_mode != 0) AND(object->texture != NULL)
  373.         AND normal_check_mode AND object->texture_modify_normal)
  374.     {
  375.       k = DOT_PRODUCT(old_normal, lighting);
  376.       diffuse = DOT_PRODUCT(*normal, lighting);
  377.       if ((k < 0.0) == (diffuse > 0.0))
  378.         diffuse = -diffuse;
  379.     } else
  380.       diffuse = DOT_PRODUCT(*normal, lighting);
  381.     if (diffuse < 0.0)
  382.     {
  383.       opposite_light = TRUE;
  384.       if (refractive AND(light_mode == 2))
  385.         diffuse = -diffuse;
  386.     } else
  387.       opposite_light = FALSE;
  388.     if ((diffuse > ROUNDOFF)
  389.         AND COLOR_BIG(surface_diffuse, ROUNDOFF))
  390.     {
  391.       intensity = light_intensity(l, &lighting);
  392.       diffuse *= intensity;
  393.     } else
  394.       diffuse = 0.0;
  395.     if (COLOR_BIG(surface_specular, ROUNDOFF))
  396.     {
  397.       if (opposite_light)
  398.         if (refractive AND(light_mode == 2))
  399.           specular = DOT_PRODUCT(refracted.vector, lighting);
  400.         else
  401.           specular = 0.0;
  402.       else
  403.         specular = DOT_PRODUCT(reflected.vector, lighting);
  404.       if (specular > ROUNDOFF)
  405.       {
  406.         if (intensity < 0.0)
  407.           intensity = light_intensity(l, &lighting);
  408.         if (intensity > ROUNDOFF)
  409.           specular = POWER(specular, new_surface.phong_factor) * intensity;
  410.         else
  411.           specular = 0.0;
  412.       }
  413.     } else
  414.       specular = 0.0;
  415.     if ((diffuse < ROUNDOFF) AND(specular < ROUNDOFF))
  416.     {
  417.       if (shade_level < LIGHT_CACHE_LEVEL_MAX)
  418.         light[l].cache_id[shade_level] = NO_OBJECTS;
  419.       continue;
  420.     }
  421.     light_brightness(object->id, l, position, &lighting, &brightness);
  422.     if (brightness.r > ROUNDOFF)
  423.     {
  424.       new_diffuse = diffuse * new_surface.diffuse_factor.r;
  425.       if (new_diffuse > ROUNDOFF)
  426.         color->r += new_diffuse * brightness.r * new_surface.diffuse.r;
  427.       if (specular > ROUNDOFF)
  428.         color->r += specular * brightness.r * new_surface.specular.r;
  429.     }
  430.     if (brightness.g > ROUNDOFF)
  431.     {
  432.       new_diffuse = diffuse * new_surface.diffuse_factor.g;
  433.       if (new_diffuse > ROUNDOFF)
  434.         color->g += new_diffuse * brightness.g * new_surface.diffuse.g;
  435.       if (specular > ROUNDOFF)
  436.         color->g += specular * brightness.g * new_surface.specular.g;
  437.     }
  438.     if (brightness.b > ROUNDOFF)
  439.     {
  440.       new_diffuse = diffuse * new_surface.diffuse_factor.b;
  441.       if (new_diffuse > ROUNDOFF)
  442.         color->b += new_diffuse * brightness.b * new_surface.diffuse.b;
  443.       if (specular > ROUNDOFF)
  444.         color->b += specular * brightness.b * new_surface.specular.b;
  445.     }
  446.   }
  447. }
  448.